#ifndef SERV_H
#define SERV_H

#include "srviface.h"

#include "LocaleFormatter.h"
#include "KeywordSubstitutor.h"
#include "StrTableMgr.h"

#include "webservicecall.h"

class Connection;
class R250;

class Server : public ServerInterface
{
	public:
		Server(int port,const String& sAppName);
		virtual ~Server();

		bool8 initSuccess();
		void run();
		void stop();
        
		void unpauseReq(Connection*);

      
		Connection*			active;

		

		uint32 rand();

		void close(Connection*);			// phase 1: client wants to close
		void readyForDeath(Connection*);	// phase 2: client finished closing

	
		// String table management
		bool8 loadStringTableForLanguage( const String& sLang );
		bool8 getString( const String& sLang, const String& sKey, String& sString );		

	protected:

		bool8	startListening();
		void	stopListening();
		bool8	startTimer(); //RPFX 8.4.1
		void	SetAccountServer(bool8); //RPFX 8.4.1

    	

		virtual bool8 startWorkers();
		virtual bool8 createWorkers();
		virtual void  stopWorkers();

		void	handleNewClient(SOCKET);

		static uint32 __stdcall workerProc(Server*);
		static uint32 __stdcall randThreadProc(Server*);

		void	addActive(Connection*);
		void	close(Connection*, bool8);
		void	kill(Connection*, bool8);
		bool8	allStale(uint32);
	

		
		// String table management		
		virtual void getStringTableName( String& tableName ) const;	
		
		// We have to have one string table loaded for each language that
		//   is currently being used
		class LangStringTableEntry
		{
		public:
			Library::LocaleFormatter*    m_pLoc;
			Library::KeywordSubstitutor* m_pKey;
			Library::StrTableMgr*        m_pStrTblMgr;

			LangStringTableEntry( const String& sLangCode ) : m_pLoc(NULL), m_pKey(NULL), m_pStrTblMgr(NULL)
			{
				m_pLoc = new Library::LocaleFormatter();
				m_pLoc->SetCurrentLanguageCode( sLangCode );
				m_pKey = new Library::KeywordSubstitutor( m_pLoc );
				m_pStrTblMgr = new Library::StrTableMgr( m_pKey, m_pLoc );
			}

			~LangStringTableEntry()
			{
				delete m_pStrTblMgr;
				delete m_pKey;
				delete m_pLoc;
			}
		};

	protected:
		virtual	Connection* createConnection(SOCKET);

    public:
        virtual bool8 OnWorkerStarted();
        virtual bool8 OnWorkerStopping();

		// CSN-8891
		WebServiceCall* webServiceCall;

	protected:
		SOCKET				server;
		HANDLE				stopEvt;
		HANDLE				shutdown;
		HANDLE				accepted;
		PCRITICAL_SECTION	mutex;
		HANDLE*				worker;
		uint8				startedUp;
		HANDLE				randThread;
		uint32				randSeed;
		PCRITICAL_SECTION	randMutex;
		PCRITICAL_SECTION	langMutex;
		R250*				r250;

		int32				numWorkers;
		HANDLE				completion;
		//Connection*			active;
		Connection*			dead;
		int32				numActive;

		HANDLE				listenNow;
		int32				isListening;

		HashTable<LangStringTableEntry*>* m_pLangTable;
		String							  m_sErrorTableName;
        String              strAppName;
		int32				isAccountServer;	//RPFX 8.4.1
		HANDLE				mhTimerQueue;		//RPFX 8.4.1	

		
     
};

#endif
